package xin.marcher.module.construction.repository;

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Repository;
import xin.marcher.framework.common.util.data.DataCuttingUtil;
import xin.marcher.module.common.constants.construction.ProductConstants;
import xin.marcher.module.common.core.PageResult;
import xin.marcher.module.common.enums.DelFlagEnum;
import xin.marcher.module.common.enums.construction.AuditCustomTypeEnum;
import xin.marcher.module.common.enums.construction.AuditExceptionCode;
import xin.marcher.module.common.enums.construction.AuditStatusEnum;
import xin.marcher.module.common.enums.construction.AuditorRoleEnum;
import xin.marcher.module.common.exception.ProductBizException;
import xin.marcher.module.common.exception.ProductErrorCodeEnum;
import xin.marcher.module.construction.builder.FullDraftData;
import xin.marcher.module.construction.builder.FullProductData;
import xin.marcher.module.construction.converter.AuditConverter;
import xin.marcher.module.construction.domain.dto.*;
import xin.marcher.module.construction.domain.entity.*;
import xin.marcher.module.construction.domain.request.AuditRequest;
import xin.marcher.module.construction.domain.request.AuditorListConfigRequest;
import xin.marcher.module.construction.domain.request.QueryTodoListRequest;
import xin.marcher.module.construction.mapper.*;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 商品审核 资源管理
 */
@Repository
public class ProductAuditRepository {

    @Resource
    private AuditConverter auditConverter;

    @Resource
    private AuditContentConfigMapper auditContentConfigMapper;

    @Resource
    private AuditInfoMapper auditInfoMapper;

    @Resource
    private AuditHistoryMapper auditHistoryMapper;
    @Resource
    private DraftMainMapper draftMainMapper;
    @Resource
    private DraftImgMapper draftImgMapper;

    @Resource
    private AuditorListConfigMapper auditorListConfigMapper;

    /**
     * 验证是否需要审核
     *
     * @param fullProductData
     * @return
     */
    public Boolean needAudit(FullProductData fullProductData, Boolean createFlag) {
        ItemInfoDO itemInfoDO = fullProductData.getItemInfoDO();
        Integer count = 0;
        if (!createFlag) {
            //1. 首先判断 商品审核内容配置表 中是否有对应的skuId
            List<String> skuIds = fullProductData.getSkuInfoDOList().stream().map(SkuInfoDO::getSkuId).collect(Collectors.toList());
            count = countByCustomIds(skuIds, AuditCustomTypeEnum.SKU);
            if (count > 0) {
                return true;
            }
            //2. 是否有对应的item
            count = countByCustomIds(Collections.singletonList(itemInfoDO.getItemId()), AuditCustomTypeEnum.ITEM);
            if (count > 0) {
                return true;
            }
        }
        //3. 验证是否有对应的categoryId
        List<Integer> categoryIds = Arrays.asList(itemInfoDO.getFirstCategoryId(), itemInfoDO.getSecondCategoryId(), itemInfoDO.getThirdCategoryId());

        count = countByCustomIds(categoryIds, AuditCustomTypeEnum.CATEGORY);
        // 当 商品审核内容配置表 中有相应的品类数据，则需要审核，否则不需要审核
        return count > 0;
    }

    /**
     * 保存草稿信息
     *
     * @param fullDraftData
     */
    public void saveDraft(FullDraftData fullDraftData) {
        //1. 保存工单信息
        AuditInfoDO auditInfoDO = saveAudit(fullDraftData);
        //2. 保存工单审核历史信息
        saveAuditHistory(auditInfoDO);
        //3. 保存草稿信息
        saveDraftMain(fullDraftData, auditInfoDO.getId());
        //4. 保存草稿图片信息
        saveDraftImgBatch(fullDraftData);
    }

    /**
     * 获取用户审核角色
     *
     * @param userId
     * @return
     */
    public AuditorListConfigDO getAuditorRuleByUserId(Integer userId) {
        LambdaQueryWrapper<AuditorListConfigDO> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(AuditorListConfigDO::getAuditorId, userId);
        AuditorListConfigDO auditorListConfigDO = auditorListConfigMapper.selectOne(queryWrapper);
        // 判断是否查询到对应的权限信息
        if (Objects.isNull(auditorListConfigDO)) {
            throw new ProductBizException(AuditExceptionCode.USER_AUDIT_RULE_NULL);
        }
        return auditorListConfigDO;
    }

    /**
     * 获取用户可审核的详细列表
     *
     * @param queryTodoListRequest
     * @param auditor
     * @return
     */
    public PageResult<AuditInfoDTO> pageResult(QueryTodoListRequest queryTodoListRequest, AuditorListConfigDO auditor) {

        LambdaQueryWrapper<AuditInfoDO> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(AuditInfoDO::getTicketStatus, AuditStatusEnum.UNAUDITED.getCode());
        Page<AuditInfoDO> page = new Page<>(queryTodoListRequest.getPageNum(), queryTodoListRequest.getPageSize());

        Integer auditorRole = auditor.getAuditorRole();
        // 不是拥有所有审核权限，则增加限定条件，指定是建品审核或者是价格审核
        if (!Objects.equals(AuditorRoleEnum.ADMIN.getCode(), auditorRole)) {
            queryWrapper.eq(AuditInfoDO::getTicketType, auditorRole);
        }
        // 根据角色查询待办列表
        return auditConverter.converterPageResult(auditInfoMapper.selectPage(page, queryWrapper));
    }

    /**
     * 查询草稿明细信息
     *
     * @param ticketId
     * @return
     */
    public DraftDetailDTO getDraftDetail(Long ticketId) {
        //1.  查询草稿主表信息
        DraftMainDTO draftMainDTO = auditConverter.convertDTO(getByTicketId(ticketId));
        //2. 查询草稿图片列表信息
        List<DraftImgDTO> draftImgDTOS = getByDraft(draftMainDTO);
        // 返回草稿的主体信息
        return new DraftDetailDTO(draftMainDTO, draftImgDTOS);
    }

    /**
     * 验证是否可审核，并返回审核对象
     *
     * @param auditRequest
     */
    public AuditInfoDTO checkAudit(AuditRequest auditRequest) {
        Long ticketId = auditRequest.getTicketId();
        // 查询审核工单
        AuditInfoDO auditInfoDO = auditInfoMapper.selectById(ticketId);
        if (Objects.isNull(auditInfoDO)) {
            throw new ProductBizException(AuditExceptionCode.USER_AUDIT_INFO_NULL);
        }
        AuditInfoDTO auditInfoDTO = auditConverter.convertAuditDTO(auditInfoDO);
        // 获取审核工单的详情
        DraftMainDO draftMainDO = getByTicketId(ticketId);
        if (Objects.isNull(draftMainDO)) {
            throw new ProductBizException(AuditExceptionCode.USER_AUDIT_INFO_NULL.getErrorCode(), "审核工单详情信息不存在");
        }
        // 验证权限是否满足
        AuditorListConfigDO auditorListConfigDO = getAuditorRuleByUserId(auditRequest.getOperatorUser());
        if (Objects.isNull(auditorListConfigDO)) {
            throw new ProductBizException(AuditExceptionCode.USER_AUDIT_RULE_NULL);
        }
        // 不是超级审核权限，并且拥有的审核权限与审核类型不一致
        if (!Objects.equals(AuditorRoleEnum.ADMIN.getCode(), auditorListConfigDO.getAuditorRole())
                && !Objects.equals(draftMainDO.getTicketType(), auditorListConfigDO.getAuditorRole())) {
            throw new ProductBizException(ProductErrorCodeEnum.AUDIT_ERROR);
        }
        auditInfoDTO.setDraftMainDTO(auditConverter.convertDTO(draftMainDO));
        return auditInfoDTO;
    }

    /**
     * 修改审核信息
     *
     * @param auditRequest
     * @param auditInfoDTO
     */
    public void updateAudit(AuditRequest auditRequest, AuditInfoDTO auditInfoDTO) {
        DraftMainDTO draftMainDTO = auditInfoDTO.getDraftMainDTO();
        // 删除草稿表数据
        deleteDraftMain(draftMainDTO);
        //修改审核表信息
        updateAudit(auditInfoDTO, auditRequest);
        // 新增审核历史记录
        saveAuditHistory(auditRequest);
    }

    /**
     * 新增审核人员配置
     *
     * @param request
     */
    public void saveAuditorConfig(AuditorListConfigRequest request) {
        AuditorListConfigDO auditorListConfigDO = auditConverter.requestToEntity(request);
        auditorListConfigDO.initCommon();
        int count = auditorListConfigMapper.insert(auditorListConfigDO);
        if (count <= 0) {
            throw new ProductBizException(AuditExceptionCode.AUDIT_SQL);
        }
    }

    /**
     * 修改审核人员配置
     *
     * @param request
     */
    public void updateAuditorConfig(AuditorListConfigRequest request) {
        LambdaUpdateWrapper<AuditorListConfigDO> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.set(StringUtils.isNotEmpty(request.getAuditorName()), AuditorListConfigDO::getAuditorName, request.getAuditorName());
        updateWrapper.set(Objects.nonNull(AuditorRoleEnum.getByCode(request.getAuditorRole())), AuditorListConfigDO::getAuditorRole, request.getAuditorRole());
        updateWrapper.eq(AuditorListConfigDO::getAuditorId, request.getAuditorId());
        int count = auditorListConfigMapper.update(null, updateWrapper);
        if (count <= 0) {
            throw new ProductBizException(AuditExceptionCode.AUDIT_SQL);
        }
    }

    /**
     * 删除审核人员配置
     *
     * @param auditorIdList
     */
    public void deleteAuditorConfig(List<Integer> auditorIdList) {
        LambdaUpdateWrapper<AuditorListConfigDO> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.in(CollectionUtils.isNotEmpty(auditorIdList), AuditorListConfigDO::getAuditorId, auditorIdList);
        updateWrapper.set(AuditorListConfigDO::getDelFlag, DelFlagEnum.DISABLED.getCode());
        int count = auditorListConfigMapper.update(null, updateWrapper);
        if (count <= 0) {
            throw new ProductBizException(AuditExceptionCode.AUDIT_SQL);
        }
    }

    /**
     * 查询审核人员配置
     *
     * @param auditorIdList
     * @return
     */
    public List<AuditorListConfigDTO> queryAuditorConfig(List<Integer> auditorIdList) {
        List<AuditorListConfigDTO> auditContentConfigList = new ArrayList<>();
        // 一次最大查询200个数据，多个分页查询,这里做数据切割
        List<List<Integer>> splitList = DataCuttingUtil.dataCuttingString(auditorIdList, ProductConstants.QUERY_ITEM_MAX_COUNT);
        for (List<Integer> auditorIds : splitList) {
            LambdaQueryWrapper<AuditorListConfigDO> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.in(AuditorListConfigDO::getAuditorId, auditorIds);
            queryWrapper.eq(AuditorListConfigDO::getDelFlag, DelFlagEnum.EFFECTIVE.getCode());
            // 分批次查询
            List<AuditorListConfigDO> stageList = auditorListConfigMapper.selectList(queryWrapper);
            if (!CollectionUtils.isEmpty(stageList)) {
                auditContentConfigList.addAll(auditConverter.listEntityToDTO(stageList));
            }
        }
        return auditContentConfigList;
    }

    /**
     * 逻辑删除草稿表数据
     *
     * @param draftMainDTO
     */
    private void deleteDraftMain(DraftMainDTO draftMainDTO) {
        DraftMainDO draftMainDO = auditConverter.converterDO(draftMainDTO);
        draftMainDO.setDelFlag(DelFlagEnum.DISABLED.getCode());

        // 草稿表数据删除
        int count = draftMainMapper.updateById(draftMainDO);
        if (count <= 0) {
            throw new ProductBizException(AuditExceptionCode.AUDIT_SQL);
        }
    }

    /**
     * 新增审核历史记录
     *
     * @param auditRequest
     */
    private void saveAuditHistory(AuditRequest auditRequest) {
        AuditHistoryDO auditHistoryDO = auditConverter.converterHistoryDO(auditRequest);
        auditHistoryDO.initCommon();
        int count = this.auditHistoryMapper.insert(auditHistoryDO);
        if (count <= 0) {
            throw new ProductBizException(AuditExceptionCode.AUDIT_SQL);
        }
    }

    /**
     * 修改审核表信息
     *
     * @param auditInfoDTO
     * @param auditRequest
     */
    private void updateAudit(AuditInfoDTO auditInfoDTO, AuditRequest auditRequest) {
        AuditInfoDO auditInfoDO = auditConverter.convertAuditDO(auditInfoDTO);
        auditInfoDO.setTicketStatus(auditRequest.getAuditStatus());
        auditInfoDO.setUpdateUser(auditRequest.getOperatorUser());
        auditInfoDO.setUpdateTime(new Date());
        int count = this.auditInfoMapper.updateById(auditInfoDO);
        if (count <= 0) {
            throw new ProductBizException(AuditExceptionCode.AUDIT_SQL);
        }
    }

    private List<DraftImgDTO> getByDraft(DraftMainDTO draftMainDTO) {
        LambdaQueryWrapper<DraftImgDO> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(DraftImgDO::getDraftId, draftMainDTO.getId());
        return auditConverter.convertImgDTO(draftImgMapper.selectList(queryWrapper));
    }

    /**
     * 保存草稿图片信息
     *
     * @param fullDraftData
     */
    private void saveDraftImgBatch(FullDraftData fullDraftData) {
        List<DraftImgDO> draftImgDOS = fullDraftData.getDraftImgDOS();
        if (!CollectionUtils.isEmpty(draftImgDOS)) {
            for (DraftImgDO draftImgDO : draftImgDOS) {
                draftImgDO.setDraftId(fullDraftData.getDraftMainDO().getId());
            }
            draftImgMapper.saveBatch(draftImgDOS);
        }
    }

    /**
     * 查询
     *
     * @param ticketId
     * @return
     */
    public DraftMainDO getByTicketId(Long ticketId) {
        LambdaQueryWrapper<DraftMainDO> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(DraftMainDO::getTicketId, ticketId);
        return draftMainMapper.selectOne(queryWrapper);
    }

    /**
     * 保存工单审核历史信息
     *
     * @param auditInfoDO
     */
    private void saveAuditHistory(AuditInfoDO auditInfoDO) {
        AuditHistoryDO auditHistoryDO = auditConverter.converterHistoryDO(auditInfoDO);
        int count = this.auditHistoryMapper.insert(auditHistoryDO);
        if (count <= 0) {
            throw new ProductBizException(AuditExceptionCode.AUDIT_SQL.getErrorCode(), "保存工单审核历史信息失败");
        }
    }

    /**
     * 保存草稿信息
     *
     * @param fullDraftData
     * @param auditId
     */
    private void saveDraftMain(FullDraftData fullDraftData, Long auditId) {
        DraftMainDO draftMainDO = fullDraftData.getDraftMainDO();
        draftMainDO.setTicketId(auditId);
        int count = draftMainMapper.insert(draftMainDO);
        if (count <= 0) {
            throw new ProductBizException(AuditExceptionCode.AUDIT_SQL.getErrorCode(), "保存草稿审核信息失败");
        }
    }

    /**
     * 保存工单信息
     *
     * @param fullDraftData
     * @return
     */
    private AuditInfoDO saveAudit(FullDraftData fullDraftData) {
        AuditInfoDO auditInfoDO = auditConverter.converterDO(fullDraftData.getDraftMainDO());
        auditInfoDO.initCommon();
        int count = auditInfoMapper.insert(auditInfoDO);
        if (count <= 0) {
            throw new ProductBizException(AuditExceptionCode.AUDIT_SQL.getErrorCode(), "保存工单失败");
        }
        return auditInfoDO;
    }

    /**
     * 统计定制id对应的数量
     *
     * @param customIds
     * @param auditCustomTypeEnum
     * @return
     */
    private Integer countByCustomIds(List customIds, AuditCustomTypeEnum auditCustomTypeEnum) {
        LambdaQueryWrapper<AuditContentConfigDO> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(AuditContentConfigDO::getCustomType, auditCustomTypeEnum.getCode())
                .in(AuditContentConfigDO::getCustomId, customIds);
        return auditContentConfigMapper.selectCount(queryWrapper);
    }


}
